package com.whenimdrunk.negocio;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.util.SparseBooleanArray;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.ArrayAdapter;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.SectionIndexer;

import com.whenimdrunk.R;
import com.whenimdrunk.MainActivity;
import com.whenimdrunk.entidades.Bloqueados;
import com.whenimdrunk.persistencia.BloqueadorHelper;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

public class ListaContactos extends Activity{

    public static Activity aListaContactos;

    private static final int REQUEST_CHOOSE_PHONE = 1;

    private MyIndexerAdapter<String> adapter;
    private ListView listaContactos;

    //Creamos un HashMap donde la clave será el teléfono para poder
    //buscar por teléfono los bloqueados
    private static HashMap<String,String> hContactos =
        new HashMap<String,String>();

    //Creamos un TreeMap ordenado por nombre de contactos para
    //poder crear una lista ordenada que mostraremos en pantalla
    private static TreeMap<String,ArrayList<String>> tContactos =
        new TreeMap<String, ArrayList<String>>();

    //Creamos un ArrayList para cargar los contactos a mostrar en pantalla
    private static ArrayList<String> list = new ArrayList<String>();

    private BloqueadorHelper bloqueadorTelefonos = null;

    private static final String[] PROJECTION_PHONE = new String[] {
        ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
        ContactsContract.CommonDataKinds.Phone.NUMBER
    };

    /**
     * Método que se ejecuta al inicio de la actividad
     *
     * @param savedInstanceState
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        //setContentView(R.layout.lista_contactos);

        //Añadir el contacts_title

        //Request for custom title bar
        this.requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
        //set to your layout file
        setContentView(R.layout.lista_contactos);
        //Set the titlebar layout
        this.getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.contacts_title);

        ImageButton validarContactos = (ImageButton ) findViewById(R.id.validar);
        validarContactos.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                validarContactos(v);
            }
        });
        //Fin añadir el contacts_title

        aListaContactos = this;

        //Creamos la BD
        bloqueadorTelefonos = new BloqueadorHelper(this);

        findViewsById();

        //Si la lista no esta cargada hacemos la consulta de los contactos.
        if(list!=null && list.size()==0){
            //Consultamos los contactos y creamos dos hash con ellos,
            //uno donde la clave es el nombre del contacto y en el otro
            //el número de teléfono
            consultarContactos();

            //Creamos la lista de contactos(Solo con el nombre del contacto)
            list = crearListaContactosAMostrar(list);

        }

        listaContactos.setFastScrollEnabled(true);

        adapter = new MyIndexerAdapter<String>(
            getApplicationContext(), android.R.layout.simple_list_item_multiple_choice,
            list);
        listaContactos.setAdapter(adapter);

        listaContactos.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);

        //Chequeamos los contactos bloqueados
        chequearBloqueados(list);

    }

    /**
     * Clase adapter customizada para mostrar un scroll que vaya mostrando las
     * letras en la lista de contactos
     *
     * @param <T>
     */
    class MyIndexerAdapter<T> extends ArrayAdapter<T> implements SectionIndexer {

        ArrayList<String> myElements;
        HashMap<String, Integer> alphaIndexer;

        String[] sections;

        public MyIndexerAdapter(Context context, int textViewResourceId,
                                List<T> objects) {
            super(context, textViewResourceId, objects);
            myElements = (ArrayList<String>) objects;
            // here is the tricky stuff
            alphaIndexer = new HashMap<String, Integer>();
            // in this hashmap we will store here the positions for
            // the sections

            int size = list.size();
            for (int i = size - 1; i >= 0; i--) {
                String element = list.get(i);
                alphaIndexer.put(element.substring(0, 1), i);
                //We store the first letter of the word, and its index.
                //The Hashmap will replace the value for identical keys are putted in
            }

            // now we have an hashmap containing for each first-letter
            // sections(key), the index(value) in where this sections begins

            // we have now to build the sections(letters to be displayed)
            // array .it must contains the keys, and must (I do so...) be
            // ordered alphabetically

            Set<String> keys = alphaIndexer.keySet(); // set of letters ...sets
            // cannot be sorted...

            Iterator<String> it = keys.iterator();
            ArrayList<String> keyList = new ArrayList<String>(); // list can be
            // sorted

            while (it.hasNext()) {
                String key = it.next();
                keyList.add(key);
            }

            Collections.sort(keyList);

            sections = new String[keyList.size()]; // simple conversion to an
            // array of object
            keyList.toArray(sections);

        }

        @Override
        public int getPositionForSection(int section) {
            //Log.v("getPositionForSection", ""+section);
            String letter = sections[section];

            return alphaIndexer.get(letter);
        }

        @Override
        public int getSectionForPosition(int position) {

            //you will notice it will be never called (right?)
            //Log.v("getSectionForPosition", "called");
            return 0;
        }

        @Override
        public Object[] getSections() {

            return sections;// to string will be called each object, to display the letter

        }

    }

    private void findViewsById() {

        listaContactos = (ListView) findViewById(R.id.ListaContactos);

    }

    /**
     * Método que realiza la consulta de los contactos
     */
    private void consultarContactos(){

        String orderBy = ContactsContract.Contacts.DISPLAY_NAME +
            " COLLATE LOCALIZED ASC";

        //Consulta que obtiene los nombres y teléfonos de los contactos
        Cursor phones = getContentResolver().query(
            ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
            PROJECTION_PHONE,
            null,
            null,
            orderBy);//Order By

        ArrayList<String> aTelefonos = null;

        while (phones.moveToNext()) {

            String contact = phones.getString(phones.getColumnIndex(
                ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
            String phoneNumber = phones.getString(phones.getColumnIndex(
                ContactsContract.CommonDataKinds.Phone.NUMBER)).trim();

            //Con esto evitamos que se añadan dos teléfonos iguales que tengan
            //diferentes nombres
            if(!hContactos.containsKey(phoneNumber)){

                //Algunos contactos pueden tener varios teléfonos asi que los vamos
                //añadiendo en un array
                aTelefonos = new ArrayList<String>();
                if(tContactos.containsKey(contact)){
                    aTelefonos = tContactos.get(contact);
                    aTelefonos.add(phoneNumber);
                }else{
                    aTelefonos.add(phoneNumber);
                }

                //Hash clave nombre
                tContactos.put(contact, aTelefonos);
                //Hash clave teléfono
                hContactos.put(phoneNumber, contact);

            }
        }

    }

    /**
     * Método que crea la lista de contactos a mostrar en pantalla
     *
     * @param list
     * @return ArrayList<String> Lista de contactos
     */
    public ArrayList<String> crearListaContactosAMostrar(ArrayList<String> list){

        if(!tContactos.isEmpty()){

            //Recorremos el TreeMap de los contactos y vamos añadiendo a un Hash cada
            //contacto con su número o números.
            //Además iremos añadiendo a la lista a mostrar en pantalla los nombres de contacto
            Iterator it = tContactos.entrySet().iterator();
            while (it.hasNext()) {
                Map.Entry e = (Map.Entry)it.next();
                //Esta es la lista que se mostrará en pantalla asi que saldrá ordenada
                //por nombre porque es como esta ordenado el TreeMap
                list.add(e.getKey().toString());
            }

        }

        return list;

    }

    /**
     * Método que marca como checkeados los contactos seleccionados para el bloqueo
     *
     * @param list
     */
    public void chequearBloqueados(ArrayList<String> list){

        //Miramos si en BD hay teléfonos bloqueados y si los hay recorremos el adapter
        //para ir checkeandolos
        ArrayList<Bloqueados> telefonosBloqueados = new ArrayList<Bloqueados>();
        bloqueadorTelefonos.getBloqueados(telefonosBloqueados);

        if(telefonosBloqueados!=null && telefonosBloqueados.size()>0){

            String[] arrayTest = new String[list.size()];
            arrayTest = list.toArray(arrayTest);

            for(Bloqueados telefono : telefonosBloqueados){

                //Busco el nombre del contacto en el hash que tiene como clave el teléfono
                String nombreContacto = hContactos.get(telefono.getTelefono());
                //Busco en el array de contactos la posicion del contacto para luego checkearlo
                int position = Arrays.binarySearch(arrayTest, nombreContacto);
                //Se checkea el contacto
                listaContactos.getItemAtPosition(position);
                listaContactos.setItemChecked(position, true);

            }

        }

    }

    /**
     * Método que graba los cambios en la configuración de contactos
     *
     * @param dialogInterface
     */
    public void validarContactos(View dialogInterface) {

        //Recogemos los contactos seleccionados
        SparseBooleanArray checked = listaContactos.getCheckedItemPositions();
        ArrayList<Bloqueados> telefonosBloqueados = new ArrayList<Bloqueados>();

        Bloqueados bloqueado = null;
        for (int i = 0; i < checked.size(); i++) {
            // Item position in adapter
            int position = checked.keyAt(i);

            //Por cada contacto seleccionado cogeremos sus teléfonos y los añadiremos
            //a un Array
            if (checked.valueAt(i)){
                ArrayList<String> aTelefonos =
                        tContactos.get(adapter.getItem(position));

                for(String telefono : aTelefonos){
                    bloqueado = new Bloqueados(telefono);
                    telefonosBloqueados.add(bloqueado);
                }
            }
        }

        //Primero borramos los bloqueados para luego insertarlos
        bloqueadorTelefonos.deleteBloqueados();
        //Ahora tenemos que almacenar en BD los teléfonos seleccionados
        bloqueadorTelefonos.insertBloqueados(telefonosBloqueados);

        //Finalizamos la actividad para que no se quede en la pila
        finish();

        volver();

    }

    /**
     * Método que vuelve al inicio de la aplicación
     */
    public void volver(){

        Intent intent = new Intent(this, MainActivity.class);
        startActivityForResult(intent, REQUEST_CHOOSE_PHONE);

    }

}
